import { Byte } from '../../api/io/Byte';
import { DropContent } from './DropContent';
import { ITimer } from '../../api/timer/ITimer';
import { IAsync } from '../../api/event/IAsync';



/**邮件属性枚举*/
export const enum E_Mail {
	/**邮件id*/
	MAIL_ID = 0,
	/**邮件类型*/
	MAIL_TYPE = 1,
	/**已读*/
	READED = 2,
	/**0-无奖励，1-有 + 未领取，2-有 + 已领取*/
	REWARD_STATUS = 3,
	/**创建时间*/
	CREATE_TIME = 4,
	/**有效时间，0-无限制*/
	VALID_TIME = 5,
	/**邮件来源类型 枚举*/
	MAIL_FROM_TYPE = 6,
	/**邮件配置id*/
	CONFIG_ID = 7,
	/**运营邮件的标题*/
	MAIL_TITLE = 8,
	/**运营邮件的内容*/
	MAIL_BODY = 9,
	/**运营邮件的发送者*/
	MAIL_SENDER = 10,
	/**已有掉落*/
	DROP = 11,
	/**邮件参数*/
	PARAM = 12,
	/**枚举数量*/
	EnumCount = 13
}


/**邮件*/
export class Mail {
	/**事件ID*/
	public static readonly EVENT_ID = 'STRUCT_DATA_MAIL_EVENT_ID';
	/**整体更新事件ID（部分只需要监听整体变化）*/
	public static readonly TOTAL_EVENT_ID = 'STRUCT_DATA_MAIL_TOTAL_EVENT_ID';
	/**缓存池*/
	private static POOL: Mail[] = [];

	/**创建入口*/
	public static create(json?: string): Mail {
		const c = this.POOL.pop() || new Mail();
		c._destroyed = false;
		c.resetProperty();
		if (json) {
			c.parse(json);
		}
		return c;
	}


	/**已释放*/
	protected _destroyed = false;
	/**邮件id (long)*/
	protected _mailId: number;
	/**邮件类型 (uint8)*/
	protected _mailType: number;
	/**已读*/
	protected _readed: boolean;
	/**0-无奖励，1-有 + 未领取，2-有 + 已领取 (uint8)*/
	protected _rewardStatus: number;
	/**创建时间 (long)*/
	protected _createTime: number;
	/**有效时间，0-无限制 (long)*/
	protected _validTime: number;
	/**邮件来源类型 枚举 (uint8)*/
	protected _mailFromType: number;
	/**邮件配置id (long)*/
	protected _configId: number;
	/**运营邮件的标题*/
	protected _mailTitle: string;
	/**运营邮件的内容*/
	protected _mailBody: string;
	/**运营邮件的发送者*/
	protected _mailSender: string;
	/**已有掉落*/
	protected _drop: DropContent = null;
	/**邮件参数*/
	protected _param: string;


	/**构建函数-私有，防止外部创建*/
	private constructor() {
	}


	/**释放*/
	public destroy(): void {
		if (this._destroyed) {
			return;
		}
		this._destroyed = true;
		this.resetProperty(true);
		if (Mail.POOL.indexOf(this) === -1) {
			Mail.POOL.push(this);
		}
	}

	/**邮件id*/
	public get mailId() {
		return this._mailId;
	}


	/**邮件id*/
	public set mailId(v: number) {
		this._mailId = v;
	}


	/**邮件类型*/
	public get mailType() {
		return this._mailType;
	}


	/**邮件类型*/
	public set mailType(v: number) {
		this._mailType = v;
	}


	/**已读*/
	public get readed() {
		return this._readed;
	}


	/**已读*/
	public set readed(v: boolean) {
		this._readed = v;
	}


	/**0-无奖励，1-有 + 未领取，2-有 + 已领取*/
	public get rewardStatus() {
		return this._rewardStatus;
	}


	/**0-无奖励，1-有 + 未领取，2-有 + 已领取*/
	public set rewardStatus(v: number) {
		this._rewardStatus = v;
	}


	/**创建时间*/
	public get createTime() {
		return this._createTime;
	}


	/**创建时间*/
	public set createTime(v: number) {
		this._createTime = v;
	}


	/**有效时间，0-无限制*/
	public get validTime() {
		return this._validTime;
	}


	/**有效时间，0-无限制*/
	public set validTime(v: number) {
		this._validTime = v;
	}


	/**邮件来源类型 枚举*/
	public get mailFromType() {
		return this._mailFromType;
	}


	/**邮件来源类型 枚举*/
	public set mailFromType(v: number) {
		this._mailFromType = v;
	}


	/**邮件配置id*/
	public get configId() {
		return this._configId;
	}


	/**邮件配置id*/
	public set configId(v: number) {
		this._configId = v;
	}


	/**运营邮件的标题*/
	public get mailTitle() {
		return this._mailTitle;
	}


	/**运营邮件的标题*/
	public set mailTitle(v: string) {
		this._mailTitle = v;
	}


	/**运营邮件的内容*/
	public get mailBody() {
		return this._mailBody;
	}


	/**运营邮件的内容*/
	public set mailBody(v: string) {
		this._mailBody = v;
	}


	/**运营邮件的发送者*/
	public get mailSender() {
		return this._mailSender;
	}


	/**运营邮件的发送者*/
	public set mailSender(v: string) {
		this._mailSender = v;
	}


	/**已有掉落*/
	public get drop() {
		return this._drop;
	}


	/**邮件参数*/
	public get param() {
		return this._param;
	}


	/**邮件参数*/
	public set param(v: string) {
		this._param = v;
	}



	/**通过枚举获取值*/
	public getV(k: E_Mail): any {
		switch (k) {
			case E_Mail.MAIL_ID: return this._mailId;
			case E_Mail.MAIL_TYPE: return this._mailType;
			case E_Mail.READED: return this._readed;
			case E_Mail.REWARD_STATUS: return this._rewardStatus;
			case E_Mail.CREATE_TIME: return this._createTime;
			case E_Mail.VALID_TIME: return this._validTime;
			case E_Mail.MAIL_FROM_TYPE: return this._mailFromType;
			case E_Mail.CONFIG_ID: return this._configId;
			case E_Mail.MAIL_TITLE: return this._mailTitle;
			case E_Mail.MAIL_BODY: return this._mailBody;
			case E_Mail.MAIL_SENDER: return this._mailSender;
			case E_Mail.DROP: return this._drop;
			case E_Mail.PARAM: return this._param;
			default: return null;
		}
	}


	/**通过枚举设置值*/
	public setV(k: E_Mail, v: any): void {
		switch (k) {
			case E_Mail.MAIL_ID: this._mailId = v; break;
			case E_Mail.MAIL_TYPE: this._mailType = v; break;
			case E_Mail.READED: this._readed = v; break;
			case E_Mail.REWARD_STATUS: this._rewardStatus = v; break;
			case E_Mail.CREATE_TIME: this._createTime = v; break;
			case E_Mail.VALID_TIME: this._validTime = v; break;
			case E_Mail.MAIL_FROM_TYPE: this._mailFromType = v; break;
			case E_Mail.CONFIG_ID: this._configId = v; break;
			case E_Mail.MAIL_TITLE: this._mailTitle = v; break;
			case E_Mail.MAIL_BODY: this._mailBody = v; break;
			case E_Mail.MAIL_SENDER: this._mailSender = v; break;
			case E_Mail.DROP: this._drop = v; break;
			case E_Mail.PARAM: this._param = v; break;
			default: break;
		}
	}


	/**初始化*/
	public resetProperty(fromDestroy = false): void {
		//邮件id
		this._mailId = 0;
		//邮件类型
		this._mailType = 0;
		//已读
		this._readed = false;
		//0-无奖励，1-有 + 未领取，2-有 + 已领取
		this._rewardStatus = 0;
		//创建时间
		this._createTime = 0;
		//有效时间，0-无限制
		this._validTime = 0;
		//邮件来源类型 枚举
		this._mailFromType = 0;
		//邮件配置id
		this._configId = 0;
		//运营邮件的标题
		this._mailTitle = '';
		//运营邮件的内容
		this._mailBody = '';
		//运营邮件的发送者
		this._mailSender = '';
		//已有掉落
		if (this._drop) {
			this._drop.destroy();
			this._drop = null;
		}
		if (!fromDestroy) {
			this._drop = DropContent.create();
		}
		//邮件参数
		this._param = '';
	}


	/**序列化*/
	public stringify(toString: boolean): string | any {
		const json: any = {};
		if (this._mailId) {
			json.mailId = this._mailId;
		}
		if (this._mailType) {
			json.mailType = this._mailType;
		}
		if (this._readed) {
			json.readed = this._readed;
		}
		if (this._rewardStatus) {
			json.rewardStatus = this._rewardStatus;
		}
		if (this._createTime) {
			json.createTime = this._createTime;
		}
		if (this._validTime) {
			json.validTime = this._validTime;
		}
		if (this._mailFromType) {
			json.mailFromType = this._mailFromType;
		}
		if (this._configId) {
			json.configId = this._configId;
		}
		if (this._mailTitle) {
			json.mailTitle = this._mailTitle;
		}
		if (this._mailBody) {
			json.mailBody = this._mailBody;
		}
		if (this._mailSender) {
			json.mailSender = this._mailSender;
		}
		if (this._drop) {
			json.drop = this._drop.stringify(false);
		}
		if (this._param) {
			json.param = this._param;
		}

		return toString ? JSON.stringify(json) : json;
	}


	/**反序列化*/
	public parse(jsonv: string | any): this {
		this.resetProperty();
		if (!jsonv) {
			return this;
		}
		const json = typeof (jsonv) === 'string' ? JSON.parse(jsonv) : jsonv;
		if (json.mailId) {
			this._mailId = json.mailId;
		}
		if (json.mailType) {
			this._mailType = json.mailType;
		}
		if (json.readed) {
			this._readed = json.readed;
		}
		if (json.rewardStatus) {
			this._rewardStatus = json.rewardStatus;
		}
		if (json.createTime) {
			this._createTime = json.createTime;
		}
		if (json.validTime) {
			this._validTime = json.validTime;
		}
		if (json.mailFromType) {
			this._mailFromType = json.mailFromType;
		}
		if (json.configId) {
			this._configId = json.configId;
		}
		if (json.mailTitle) {
			this._mailTitle = json.mailTitle;
		}
		if (json.mailBody) {
			this._mailBody = json.mailBody;
		}
		if (json.mailSender) {
			this._mailSender = json.mailSender;
		}
		if (json.drop) {
			this._drop.destroy();
			this._drop = DropContent.create(json.drop);
		}
		if (json.param) {
			this._param = json.param;
		}
		return this;
	}


	/**序列化-二进制*/
	public toBytes(byte: Byte): void {
		if (!byte) {
			return;
		}
		byte.writeLongNumber(this._mailId);
		byte.writeUint8(this._mailType);
		byte.writeBool(this._readed);
		byte.writeUint8(this._rewardStatus);
		byte.writeLongNumber(this._createTime);
		byte.writeLongNumber(this._validTime);
		byte.writeUint8(this._mailFromType);
		byte.writeLongNumber(this._configId);
		byte.writeString(this._mailTitle);
		byte.writeString(this._mailBody);
		byte.writeString(this._mailSender);
		this._drop.toBytes(byte);
		byte.writeString(this._param);
	}


	/**反序列化-二进制*/
	public fromBytes(byte: Byte): this {
		this.resetProperty();
		if (!byte) {
			return;
		}
		this._mailId = byte.readLongNumber();
		this._mailType = byte.readUint8();
		this._readed = byte.readBool();
		this._rewardStatus = byte.readUint8();
		this._createTime = byte.readLongNumber();
		this._validTime = byte.readLongNumber();
		this._mailFromType = byte.readUint8();
		this._configId = byte.readLongNumber();
		this._mailTitle = byte.readString();
		this._mailBody = byte.readString();
		this._mailSender = byte.readString();
		this._drop.fromBytes(byte);
		this._param = byte.readString();
		return this;
	}


	/**克隆*/
	public clone(): Mail {
		const byte = Byte.createFromPool();
		this.toBytes(byte);
		byte.pos = 0;
		const clonev = Mail.create().fromBytes(byte);
		Byte.recoverToPool(byte);
		return clonev;
	}


	/**处理更新*/
	public processUpdate(jsonv: string): void {
		if (!jsonv) {
			return;
		}

		const eventID = Mail.EVENT_ID;
		const us = JSON.parse(jsonv);

		for (let i = 0, len = us.length; i < len;) {
			const idx = us[i];
			//邮件id
			if (idx === E_Mail.MAIL_ID) {
				const oldv = this._mailId;
				this._mailId = us[i + 1];
				IAsync.dispatch(eventID, idx, this._mailId, oldv);
				i += 2;
				continue;
			}
			//邮件类型
			if (idx === E_Mail.MAIL_TYPE) {
				const oldv = this._mailType;
				this._mailType = us[i + 1];
				IAsync.dispatch(eventID, idx, this._mailType, oldv);
				i += 2;
				continue;
			}
			//已读
			if (idx === E_Mail.READED) {
				const oldv = this._readed;
				this._readed = us[i + 1];
				IAsync.dispatch(eventID, idx, this._readed, oldv);
				i += 2;
				continue;
			}
			//0-无奖励，1-有 + 未领取，2-有 + 已领取
			if (idx === E_Mail.REWARD_STATUS) {
				const oldv = this._rewardStatus;
				this._rewardStatus = us[i + 1];
				IAsync.dispatch(eventID, idx, this._rewardStatus, oldv);
				i += 2;
				continue;
			}
			//创建时间
			if (idx === E_Mail.CREATE_TIME) {
				const oldv = this._createTime;
				this._createTime = us[i + 1];
				IAsync.dispatch(eventID, idx, this._createTime, oldv);
				i += 2;
				continue;
			}
			//有效时间，0-无限制
			if (idx === E_Mail.VALID_TIME) {
				const oldv = this._validTime;
				this._validTime = us[i + 1];
				IAsync.dispatch(eventID, idx, this._validTime, oldv);
				i += 2;
				continue;
			}
			//邮件来源类型 枚举
			if (idx === E_Mail.MAIL_FROM_TYPE) {
				const oldv = this._mailFromType;
				this._mailFromType = us[i + 1];
				IAsync.dispatch(eventID, idx, this._mailFromType, oldv);
				i += 2;
				continue;
			}
			//邮件配置id
			if (idx === E_Mail.CONFIG_ID) {
				const oldv = this._configId;
				this._configId = us[i + 1];
				IAsync.dispatch(eventID, idx, this._configId, oldv);
				i += 2;
				continue;
			}
			//运营邮件的标题
			if (idx === E_Mail.MAIL_TITLE) {
				const oldv = this._mailTitle;
				this._mailTitle = us[i + 1];
				IAsync.dispatch(eventID, idx, this._mailTitle, oldv);
				i += 2;
				continue;
			}
			//运营邮件的内容
			if (idx === E_Mail.MAIL_BODY) {
				const oldv = this._mailBody;
				this._mailBody = us[i + 1];
				IAsync.dispatch(eventID, idx, this._mailBody, oldv);
				i += 2;
				continue;
			}
			//运营邮件的发送者
			if (idx === E_Mail.MAIL_SENDER) {
				const oldv = this._mailSender;
				this._mailSender = us[i + 1];
				IAsync.dispatch(eventID, idx, this._mailSender, oldv);
				i += 2;
				continue;
			}
			//已有掉落
			if (idx === E_Mail.DROP) {
				const fui: string = us[i + 1];
				if (this._drop) {
					this._drop.processUpdate(fui);
				}
				else {
					console.error('Mail drop is null when update.');
				}
				IAsync.dispatch(eventID, idx);
				i += 2;
				continue;
			}
			//邮件参数
			if (idx === E_Mail.PARAM) {
				const oldv = this._param;
				this._param = us[i + 1];
				IAsync.dispatch(eventID, idx, this._param, oldv);
				i += 2;
				continue;
			}

			console.error('[Struct Data] can not find enum in Mail with idx = ' + idx + ', version maybe wrong.')
		}

		//全更事件
		ITimer.callLater(this, this.dispatchTotalUpdate);
	}


	/**比对不一致结果*/
	public getCompareInfo(other: Mail): string {
		if (!other) {
			return null;
		}

		const updates: any[] = [];

		if (this._mailId !== other._mailId) {
			updates.push(E_Mail.MAIL_ID, this._mailId);
		}
		if (this._mailType !== other._mailType) {
			updates.push(E_Mail.MAIL_TYPE, this._mailType);
		}
		if (this._readed !== other._readed) {
			updates.push(E_Mail.READED, this._readed);
		}
		if (this._rewardStatus !== other._rewardStatus) {
			updates.push(E_Mail.REWARD_STATUS, this._rewardStatus);
		}
		if (this._createTime !== other._createTime) {
			updates.push(E_Mail.CREATE_TIME, this._createTime);
		}
		if (this._validTime !== other._validTime) {
			updates.push(E_Mail.VALID_TIME, this._validTime);
		}
		if (this._mailFromType !== other._mailFromType) {
			updates.push(E_Mail.MAIL_FROM_TYPE, this._mailFromType);
		}
		if (this._configId !== other._configId) {
			updates.push(E_Mail.CONFIG_ID, this._configId);
		}
		if (this._mailTitle !== other._mailTitle) {
			updates.push(E_Mail.MAIL_TITLE, this._mailTitle);
		}
		if (this._mailBody !== other._mailBody) {
			updates.push(E_Mail.MAIL_BODY, this._mailBody);
		}
		if (this._mailSender !== other._mailSender) {
			updates.push(E_Mail.MAIL_SENDER, this._mailSender);
		}
		//已有掉落
		{
			const ui = this._drop.getCompareInfo(other._drop);
			if (ui && ui.length > 0) {
				updates.push(E_Mail.DROP, ui);
			}
		}
		if (this._param !== other._param) {
			updates.push(E_Mail.PARAM, this._param);
		}

		const jsonv = updates.length === 0 ? null : JSON.stringify(updates);
		return jsonv;
	}


	/**全部更新*/
	protected dispatchTotalUpdate(): void {
		IAsync.dispatch(Mail.TOTAL_EVENT_ID, this.getV(0));
	}

}
